﻿#include <iostream>
#include <opencv2/opencv.hpp>
#include <filesystem>
#include <opencv2/features2d.hpp>


using namespace cv::dnn;
using namespace cv;
using namespace std;
namespace fs = std::filesystem;

int main()
{
	// 获取当前可执行文件的路径
	fs::path exePath = fs::current_path();
	// 构建资源文件的完整路径
	fs::path imagePath = exePath / "x64\\Debug\\img\\C++.png";
	string imgPath_str = imagePath.generic_string();


	//加载图片: 图片路径、读取图像的方式
	Mat image = imread(imgPath_str, IMREAD_COLOR);
	//可调整窗体大小
	//namedWindow("图片显示窗口", WINDOW_FREERATIO);

	if (image.empty())
	{
		cout << "没有图像\n";
		return -1;
	}
	//显示图像
	imshow("原图片窗口", image);



	cv::Mat src = cv::imread(imgPath_str, cv::IMREAD_GRAYSCALE);
	cv::Mat dst, dst_norm;


	/*
	角点检测
	角点是图像中亮度变化剧烈的点，通常位于物体的边缘或纹理丰富的区域。
	角点检测是特征检测的基础，常用的角点检测算法有 Harris 角点检测和 Shi - Tomasi 角点检测。

	Harris角点检测
	Harris 角点检测是一种经典的角点检测算法，它通过计算图像中每个像素点的自相关矩阵来判断
	该点是否为角点。自相关矩阵的特征值可以反映该点的局部结构：如果两个特征值都很大，
	则该点很可能是角点；如果一个特征值很大，另一个很小，则该点可能是边缘；如果两个
	特征值都很小，则该点可能是平坦区域。
	*/

	// Harris角点检测
	cv::cornerHarris(src, dst, 2, 3, 0.04);

	// 归一化并显示结果
	cv::normalize(dst, dst_norm, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
	cv::imshow("Harris角点检测", dst_norm);


	/*
	Shi - Tomasi 角点检测
	Shi - Tomasi角点检测是对Harris角点检测的改进，它通过计算图像中每个像素点的最小特征值来
	判断该点是否为角点。与Harris角点检测相比，Shi - Tomasi角点检测更加稳定，且计算量较小。

	在OpenCV中，可以使用cv::goodFeaturesToTrack函数来实现Shi - Tomasi角点检测：
	*/
	std::vector<cv::Point2f> corners;
	// Shi-Tomasi角点检测
	cv::goodFeaturesToTrack(src, corners, 100, 0.01, 10);
	// 绘制角点
	for (size_t i = 0; i < corners.size(); i++) {
		cv::circle(src, corners[i], 5, cv::Scalar(0, 0, 255), 2);
	}
	cv::imshow("Shi-Tomasi角点检测", src);





	/*
	特征点检测
	特征点检测是提取图像中具有独特性质的点，这些点通常具有旋转、缩放、光照不变性。常用的特征点检测算法有SIFT、SURF和ORB。
	SIFT 算法
	SIFT（Scale - Invariant Feature Transform）是一种基于尺度空间的特征点检测算法，它对图像的旋转、缩放、亮度变化具有不变性。
	SIFT算法通过检测图像中的极值点，并计算这些点的梯度方向直方图来生成特征描述子。
	在 OpenCV 中，可以使用cv::xfeatures2d::SIFT类来实现SIFT特征点检测：
	*/
	// 初始化 ORB 检测器
	Ptr<ORB> orb = ORB::create(
		500,              // 要保留的最大特征点数量
		1.2f,             // 金字塔层级之间的缩放比例
		8,                // 金字塔的层数
		31,               // 边缘阈值（避免在边缘附近提取特征）
		0,                // 第一层金字塔的初始尺度
		2,                // 生成描述子时使用的像素点范围（WTA_K）
		ORB::HARRIS_SCORE, // 使用 Harris 角点评分算法
		31,               // 补丁大小
		20                // 快速角点检测的阈值
	);
	vector<KeyPoint> keypoints;
	Mat descriptors;
	// 检测特征点并计算描述子
	orb->detectAndCompute(src, noArray(), keypoints, descriptors);
	// 在图像上绘制特征点
	Mat img_with_keypoints;
	drawKeypoints(src, keypoints, img_with_keypoints, Scalar(0, 255, 0), DrawMatchesFlags::DEFAULT);
	// 显示结果
	imshow("特征点检测ORB", img_with_keypoints);



	// SIFT（需 contrib 模块）
	Ptr<SIFT> sift = SIFT::create();
	// FAST（仅检测角点，不生成描述子）
	Ptr<FastFeatureDetector> fast = FastFeatureDetector::create(50); // 阈值
	fast->detect(src, keypoints);
	// 在图像上绘制特征点
	Mat img_with_keypoints2;
	drawKeypoints(src, keypoints, img_with_keypoints2, Scalar(0, 255, 0), DrawMatchesFlags::DEFAULT);
	// 显示结果
	imshow("特征点检测SIFT", img_with_keypoints2);






	// 转换为灰度图像
	Mat gray2;
	cvtColor(image, gray2, COLOR_BGR2GRAY);

	// 二值化
	Mat binary2;
	threshold(gray2, binary2, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);

	// 去除噪声
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
	morphologyEx(binary2, binary2, MORPH_OPEN, kernel, Point(-1, -1), 2);

	// 计算距离变换
	Mat dist;
	distanceTransform(binary2, dist, DIST_L2, 5);

	// 归一化距离变换图像
	normalize(dist, dist, 0, 1.0, NORM_MINMAX);

	// 二值化距离变换图像
	threshold(dist, dist, 0.5, 1.0, THRESH_BINARY);

	// 查找轮廓
	Mat dist_8u;
	dist.convertTo(dist_8u, CV_8U);
	vector<vector<Point>> contours;
	findContours(dist_8u, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

	// 创建标记图像
	Mat markers = Mat::zeros(dist.size(), CV_32S);
	for (size_t i = 0; i < contours.size(); i++) {
		drawContours(markers, contours, static_cast<int>(i), Scalar(static_cast<int>(i) + 1), -1);
	}

	// 应用分水岭算法
	watershed(image, markers);

	// 显示结果
	Mat result = image.clone();
	for (int i = 0; i < markers.rows; i++) {
		for (int j = 0; j < markers.cols; j++) {
			if (markers.at<int>(i, j) == -1) {
				result.at<Vec3b>(i, j) = Vec3b(0, 255, 0); // 标记边界为绿色
			}
		}
	}

	imshow("Watershed Result", result);









	//轮廓检测用于提取图像中对象的边界
	// 转换为灰度图像
	Mat gray;
	cvtColor(image, gray, COLOR_BGR2GRAY);

	// 二值化
	Mat binary;
	threshold(gray, binary, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);

	// 查找轮廓
	vector<vector<Point>> contours2;
	vector<Vec4i> hierarchy;
	findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);

	// 绘制轮廓
	Mat result2 = Mat::zeros(image.size(), CV_8UC3);
	for (size_t i = 0; i < contours2.size(); i++) {
		drawContours(result2, contours2, i, Scalar(0, 255, 0), 2);
	}

	// 显示结果
	imshow("Contours", result2);





	//形态学操作是基于形状的图像处理技术，常用于去除噪声、分离对象等。
	// 转换为灰度图像
	//Mat gray3;
	//cvtColor(image, gray, COLOR_BGR2GRAY);

	//// 二值化
	//Mat binary3;
	//threshold(gray3, binary3, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);

	//// 定义核
	//Mat kernel2 = getStructuringElement(MORPH_RECT, Size(5, 5));

	//// 开运算（去除噪声）
	//Mat opened;
	//morphologyEx(binary3, opened, MORPH_OPEN, kernel2);

	//// 闭运算（填充孔洞）
	//Mat closed;
	//morphologyEx(opened, closed, MORPH_CLOSE, kernel2);

	//// 显示结果
	//imshow("Original Binary", binary3);
	//imshow("Opened Image", opened);
	//imshow("Closed Image", closed);





	 // 转换为灰度图像
	Mat gray4;
	cvtColor(image, gray4, COLOR_BGR2GRAY);

	// 直方图均衡化
	Mat equalized;
	equalizeHist(gray4, equalized);

	// 显示结果
	imshow("Original Image", gray4);
	imshow("Equalized Image", equalized);



	// 模板匹配
	Mat result4;
	matchTemplate(image, image, result4, TM_CCOEFF_NORMED);

	// 找到最佳匹配位置
	double minVal, maxVal;
	Point minLoc, maxLoc;
	minMaxLoc(result4, &minVal, &maxVal, &minLoc, &maxLoc);

	// 绘制矩形框
	rectangle(image, maxLoc, Point(maxLoc.x + image.cols, maxLoc.y + image.rows), Scalar(0, 255, 0), 2);

	// 显示结果
	imshow("Template Matching", image);


	waitKey();
	return 0;

}
